<template>
  <vc-collection-primitive>
    <vc-primitive-cluster
      ref="primitiveClusterRef"
      :show="show"
      :enabled="enabled"
      v-if="billboards.length"
      :billboards="billboards"
      :labels="labels"
      :minimum-cluster-size="minimumClusterSize"
      @ready="onDataSourceReady"
      @cluster-event="onClusterEvent"
      @click="onClicked"
      @mouseover="onMouseOver"
    />
  </vc-collection-primitive>
</template>
<script lang="ts" setup>
import { isNullOrUnDef } from "@/utils/is";
import { PropType, reactive, unref } from "vue";
import { onMounted, ref, watch } from "vue";
import type {
  CMapExtParams,
  CMapGeojsonStyle,
  CMapLabelStyle,
} from "./types/CMapOptionConfig";
import { cloneDeep } from "lodash";
import FilterUtil from "@/utils/featureFilter/FilterUtil";
import SuperGif from "libgif";

const props = defineProps({
  show: {
    type: Boolean,
    default: () => true,
  },
  enabled: {
    type: Boolean,
    default: () => false,
  },
  minimumClusterSize: {
    type: Number,
    default: () => 2,
  },
  geoJson: {
    type: Object,
    default: () => null,
  },
  extParams: {
    type: Object as PropType<CMapExtParams>,
    default: () => ({
      pixelRange: 0,
      minimumClusterSize: 2,
      scale: 1,
    }),
  },
  txtField: {
    type: String,
    default: () => "",
  },
  txtFieldModel: {
    type: Number,
    default: () => 0,
  },
  txtStyle: {
    type: Array<CMapLabelStyle>,
    required: false,
  },
  geoStyle: {
    type: Array<CMapGeojsonStyle>,
    required: false,
  },
  whereFilter: {
    type: Array,
    required: false,
  },
  fieldRelation: {
    type: Object,
    default: () => ({}),
  },
});
const isDataSourceObjectLoading = ref<boolean>(false);
const isDataSourceShow = ref<boolean>(false);

const billboards = reactive<any[]>([]);
const labels = reactive<any>([]);
const entities = reactive<any>([]);

watch(
  () => props.geoJson,
  (_newVal, _oldVal) => {
    isDataSourceObjectLoading.value = true;
    buildDatas();
  }
);
onMounted(() => {});
const onDataSourceReady = (data: any) => {
  console.log("onDataSourceReady", data);
};
const buildDatas = () => {
  //清空原来对象变量值
  if (isDataSourceShow.value) {
    billboards.splice(0, billboards.length);
    isDataSourceShow.value = false;
    return;
  }
  if (!isDataSourceObjectLoading.value) {
    return;
  }
  if (isNullOrUnDef(props.geoJson)) {
    return;
  }
  const geojson = props.geoJson;
  if (isNullOrUnDef(geojson.features)) {
    return;
  }
  const features = geojson.features;
  const txtStyle = props.txtStyle || [];
  if (txtStyle.length > 0) {
    txtStyle.forEach((e) => {
      if (isNullOrUnDef(e)) {
        txtStyle.splice(txtStyle.indexOf(e), 1);
      }
    });
  }
  const textStyleFeature = cloneDeep(txtStyle) as any;
  const geoStyle = unref(props.geoStyle) || [];
  const geoStyleFeature = cloneDeep(geoStyle) as any;
  const wheres = unref(props.whereFilter) as [];
  if (!isNullOrUnDef(wheres) && wheres.length > 0) {
    wheres.forEach((e) => {
      if (isNullOrUnDef(e)) {
        wheres.splice(wheres.indexOf(e), 1);
      }
    });
  }
  if (!isNullOrUnDef(wheres)) {
    for (let i = 0; i < geoStyleFeature.length; i++) {
      geoStyleFeature[i].whereFilter = wheres[i];
      textStyleFeature[i].whereFilter = wheres[i];
    }
  }
  debugger;
  for (let s = 0; s < features.length; s++) {
    const feature = features[s];
    const geometry = feature.geometry;
    const properties = feature.properties;
    const coordinates = geometry.coordinates;
    const entityName =
      properties.name || properties.title || properties.guid || "";
    //根据样式信息匹配文本样式信息
    const newTextStyleFeature = FilterUtil.getMatches(
      textStyleFeature,
      properties
    );
    //根据样式信息匹配图形样式信息
    const newGeoStyleFeature = FilterUtil.getMatches(
      geoStyleFeature,
      properties
    );
    let billboard = { show: false, image: "" } as Cesium.Billboard;
    let imageName = "";
    let imageScale = 1.0;
    if (
      !isNullOrUnDef(newGeoStyleFeature) &&
      !isNullOrUnDef(newGeoStyleFeature.image)
    ) {
      imageName = newGeoStyleFeature.image;
      imageScale = newGeoStyleFeature.scale || 1.0;
      billboard = {
        show: true,
        image: getImageUrl(imageName),
        width: newGeoStyleFeature.width,
        height: newGeoStyleFeature.height,
        scale: imageScale,
        verticalOrigin: newGeoStyleFeature.verticalOrigin || Cesium.VerticalOrigin.CENTER,
      } as Cesium.Billboard;
    }
    let label = {} as any;
    let isTextTopOffset = 0;
    if (
      !(isNullOrUnDef(props.txtField) || isNullOrUnDef(newTextStyleFeature))
    ) {
      let text = properties[props.txtField] || "";
      if (!isNullOrUnDef(text)) {
        if (text.length > 10) {
          //长度过长采用中间换行方式显示
          const beginTxtLength = Math.floor(text.length / 2);
          const beginText = text.substring(0, beginTxtLength) + "\n";
          const endText = text.substring(beginTxtLength);
          text = beginText + endText;
          isTextTopOffset = -22;
        }
      }
      label = { show: true, text: text };
      if (!isNullOrUnDef(newTextStyleFeature.font)) {
        label.font = newTextStyleFeature.font;
      }
      if (!isNullOrUnDef(newTextStyleFeature.pixelOffset)) {
        label.pixelOffset = new Cesium.Cartesian2(
          newTextStyleFeature.pixelOffset![0] || 0,
          newTextStyleFeature.pixelOffset![1] + isTextTopOffset ||
            -42 + isTextTopOffset
        );
      }
      if (!isNullOrUnDef(newTextStyleFeature.scale)) {
        label.scale = newTextStyleFeature.scale;
      }
      if (!isNullOrUnDef(newTextStyleFeature.fillColor)) {
        label.fillColor = Cesium.Color.fromCssColorString(
          newTextStyleFeature.fillColor || Cesium.Color.WHITE.toCssHexString()
        );
        label.style = Cesium.LabelStyle.FILL;
      }

      if (!isNullOrUnDef(newTextStyleFeature.backgroundColor)) {
        label.backgroundColor = Cesium.Color.fromCssColorString(
          newTextStyleFeature.backgroundColor
        );
        label.showBackground = true;
      } else {
        label.showBackground = false;
      }
      if (!isNullOrUnDef(newTextStyleFeature.outlineColor)) {
        label.outlineColor = Cesium.Color.fromCssColorString(
          newTextStyleFeature.outlineColor
        );
        label.outlineWidth = newTextStyleFeature.outlineWidth || 1;
        if (!isNullOrUnDef(newTextStyleFeature.fillColor)) {
          label.style = Cesium.LabelStyle.FILL_AND_OUTLINE;
        } else {
          label.style = Cesium.LabelStyle.OUTLINE;
        }
      }

      if (!isNullOrUnDef(newTextStyleFeature.distanceDisplayCondition)) {
        const far =
          newTextStyleFeature.distanceDisplayCondition[0] || Number.MIN_VALUE;
        const near =
          newTextStyleFeature.distanceDisplayCondition[1] || Number.MAX_VALUE;
        label.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(
          far,
          near
        );
      }
      if (!isNullOrUnDef(props.txtFieldModel) && props.txtFieldModel == 1) {
        label.show = false;
      }
    } else {
      label = {
        show: false,
      };
    }
    //增加固定自定义参数
    properties["_txtFieldModel"] = unref(props.txtFieldModel);
    properties["_fieldRelation"] = unref(props.fieldRelation);
    properties["_componentName"] = unref(props.extParams.componentName);
    properties["_componentTo"] = unref(props.extParams.componentTo);
    properties["_componentWidth"] = unref(props.extParams.componentWidth);
    properties["_componentTitle"] = unref(props.extParams.componentTitle);
    if (!isNullOrUnDef(geometry)) {
      if (geometry.type === "Point") {
        label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER; //水平
        label.verticalOrigin = Cesium.VerticalOrigin.TOP; //垂直
        let heightOffset = 0;
        let z = feature.geometry.coordinates[2] || 0;
        if (
          !(
            isNullOrUnDef(newGeoStyleFeature) ||
            isNullOrUnDef(newGeoStyleFeature.heightOffset)
          )
        ) {
          heightOffset = newGeoStyleFeature.heightOffset;
          z = z + heightOffset;
        }

        if (
          !(
            isNullOrUnDef(newGeoStyleFeature) ||
            isNullOrUnDef(newGeoStyleFeature.disableDepthTestDistance)
          )
        ) {
          billboard.heightReference = 1;
          billboard.disableDepthTestDistance =
            newGeoStyleFeature.disableDepthTestDistance;
        }
        const p = Cesium.Cartesian3.fromDegrees(
          feature.geometry.coordinates[0],
          feature.geometry.coordinates[1],
          z
        );
        billboard.position = p;
        //TEST
        billboard.image = "https://zouyaoji.top/vue-cesium/images/mark-icon.png";
        billboards.push(billboard);
        // labels.push(label);
        // billboards.push({
        //   image: "https://zouyaoji.top/vue-cesium/images/mark-icon.png",
        //   width: 32,
        //   height: 32,
        //   position: [coordinates[0], coordinates[1]],
        //   _xyData: properties,
        //   onClick: (e: any) => {
        //     console.log(e);
        //   },
        // });
        labels.push({
          show: true,
          scale: 1,
          showBackground: true,
          backgroundColor:
            Cesium.Color.fromCssColorString("#000000").withAlpha(0.1),
          verticalOrigin: 1,
          horizontalOrigin: 0,
          pixelOffset: new Cesium.Cartesian2(0, -20),
          font: "16px sans-serif",
          position: [coordinates[0], coordinates[1]],
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          distanceDisplayCondition: [0, Number.POSITIVE_INFINITY],
          text: properties.name,
        });
      }
    }
  }
};

const onClusterEvent = () => {};
const onClicked = () => {};
const onMouseOver = () => {};

const getImageUrl = (name: string) => {
  // path 是否包含http/https
  if (name.indexOf("http") > -1 || name.indexOf("https") > -1) {
    return name;
  }
  const imgUrl = new URL(`../../assets/map/marker/${name}`, import.meta.url)
    .href;
  return imgUrl.toString();
};

const createGif = async (billboard: any, entity: any) => {
  let gifDiv = document.createElement("div");
  let gifImg = document.createElement("img");
  gifDiv.appendChild(gifImg);
  gifImg.src = new URL(
    `../../assets/map/marker/${billboard.image}`,
    import.meta.url
  ).href;
  await new Promise((resolve, reject) => {
    gifImg.onload = () => {
      let rub = new SuperGif({
        gif: gifImg,
      });
      rub.load(() => {
        entity.billboard.image = new Cesium.CallbackProperty(() => {
          return rub.get_canvas().toDataURL("image/png");
        }, false);

        billboards.push(entity);
      });
      resolve(entity);
    };
    gifImg.onerror = (error) => {
      reject(error);
    };
  });
};
</script>
